#include "stdafx.h"
#include <boost/test/auto_unit_test.hpp>

#include <boost/test/execution_monitor.hpp>
#include "bmock.hpp"
#include "bmock_control_tools_mock.hpp"

struct arg_tester {
	void m(int x, int &y);
};

static int y_def = 3;

static const int x_expected = 6;
static int y_expected = 7;
static const int x_actual = 10;
static int y_actual;
static const char          s_name[]     = "x";
static const std::string   s_actual     = boost::lexical_cast<std::string>(x_actual);
static const std::string   s_expected   = boost::lexical_cast<std::string>(x_expected);

static void f(int x = 5, int& y = y_def) {
	STATIC_MOCK_VOID(2, (IN(x),OUT(y)));
}
void arg_tester::m(int x = 5, int& y = y_def) {
	STATIC_MOCK_VOID(2, (IN(x),OUT(y)));
}

BOOST_AUTO_TEST_CASE(test_function_default_arguments_use_default) {
	__BMOCK_CONTROL(c);
	const bmock::control_tools_ptr t(new bmock::control_tools_mock(c));

	__BMOCK_EXPECT_C(c,f());
	__BMOCK_REPLAY_C(c);
	BOOST_CHECK_NO_THROW(f());
	__BMOCK_VERIFY_C(c);

}

BOOST_AUTO_TEST_CASE(test_function_default_arguments_not_use_default_valid_args) {
	__BMOCK_CONTROL(c);
	const bmock::control_tools_ptr t(new bmock::control_tools_mock(c));

	__BMOCK_EXPECT_C(c,f(x_expected,y_expected));
	__BMOCK_REPLAY_C(c);
	BOOST_CHECK_NO_THROW(f(x_expected, y_actual));
	__BMOCK_VERIFY_C(c);
	BOOST_CHECK_EQUAL(y_expected, y_actual);
}

BOOST_AUTO_TEST_CASE(test_function_default_arguments_not_use_default_Invalid_args) {	
	__BMOCK_CONTROL(c);
	const bmock::control_tools_ptr t(new bmock::control_tools_mock(c));
	const bmock::location          loc(__FILE__,__LINE__+7);

	__BMOCK_EXPECT_RETURN_C(c,true,t->check_equal(s_expected,s_actual,bmock::message(bmock::ARG_VALUE,s_name),loc));
	__BMOCK_EXPECT_THROW_C(c,new bmock::location(loc),t->abort(loc));
	__BMOCK_REPLAY_C(c);
	{
		bmock::test_mode_control c1(bmock::location(__FILE__,__LINE__),t);
		__BMOCK_EXPECT_C(c1,f(x_expected,y_expected));
		__BMOCK_REPLAY_C(c1);
		BOOST_CHECK_THROW(f(x_actual, y_actual),bmock::location);
	}
	__BMOCK_VERIFY_C(c);
	BOOST_CHECK_EQUAL(y_expected, y_actual);
}

BMOCK_TEST(arg_tester, test_method_default_arguments_use_default) {
	__BMOCK_CONTROL(c);
	const bmock::control_tools_ptr t(new bmock::control_tools_mock(c));

	__BMOCK_EXPECT_C(c,m());
	__BMOCK_REPLAY_C(c);
	BOOST_CHECK_NO_THROW(m());
	__BMOCK_VERIFY_C(c);

}

BMOCK_TEST(arg_tester, test_method_default_arguments_not_use_default_valid_args) {
	__BMOCK_CONTROL(c);
	const bmock::control_tools_ptr t(new bmock::control_tools_mock(c));

	__BMOCK_EXPECT_C(c,m(x_expected,y_expected));
	__BMOCK_REPLAY_C(c);
	BOOST_CHECK_NO_THROW(m(x_expected, y_actual));
	__BMOCK_VERIFY_C(c);
	BOOST_CHECK_EQUAL(y_expected, y_actual);
}

BMOCK_TEST(arg_tester, test_method_default_arguments_not_use_default_Invalid_args) {	
	__BMOCK_CONTROL(c);
	const bmock::control_tools_ptr t(new bmock::control_tools_mock(c));
	const bmock::location          loc(__FILE__,__LINE__+7);

	__BMOCK_EXPECT_RETURN_C(c,true,t->check_equal(s_expected,s_actual,bmock::message(bmock::ARG_VALUE,s_name),loc));
	__BMOCK_EXPECT_THROW_C(c,new bmock::location(loc),t->abort(loc));
	__BMOCK_REPLAY_C(c);
	{
		bmock::test_mode_control c1(bmock::location(__FILE__,__LINE__),t);
		__BMOCK_EXPECT_C(c1,m(x_expected,y_expected));
		__BMOCK_REPLAY_C(c1);
		BOOST_CHECK_THROW(m(x_actual, y_actual),bmock::location);
	}
	__BMOCK_VERIFY_C(c);
	BOOST_CHECK_EQUAL(y_expected, y_actual);
}

